package cn.ouryears.common.action;

import java.sql.Date;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.multiaction.MultiActionController;
import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;

import cn.ouryears.common.constants.WebConstants;
import cn.ouryears.common.exception.handle.ExceptionHandler;
import cn.ouryears.system.bean.OperLogBean;
import cn.ouryears.system.service.IOperLogSV;

public class BaseMultiActionController extends MultiActionController implements
		InitializingBean {

	public final Logger logger = Logger.getLogger(BaseMultiActionController.class);

	protected String errorView;

	protected String formView;

	protected BindingResult bindingResult;

	private String commandName;

	private ExceptionHandler exHandler;

	private IOperLogSV operLogSV;

	/**
     * action统一处理基类，后续用于处理request引发的exception的过滤，避免错误信息直接抛到前台
     */
	protected ModelAndView handleRequestInternal(HttpServletRequest request,
			HttpServletResponse response) throws Exception {

		if (logger.isDebugEnabled()) {
			logger.debug("Start ActionController ...");
		}

		ModelAndView _mv = null;
		Object _errorObject;
		Map _resultMap = new HashMap();
		OperLogBean log = new OperLogBean();

		try {

			log.setRequestUrl(request.getRequestURI());
			log.setRequestIp(request.getRemoteAddr());
			log.setRequestTime(new Date(System.currentTimeMillis()));
			_mv = super.handleRequestInternal(request, response);

		} catch (Exception e) {
			if (logger.isDebugEnabled()) {
				logger.debug("Exception found: Handle exception in LicMultiActionController");
			}
			logger.error("The exception is " + e);

			e.printStackTrace();

			if (exHandler == null) {
				logger.warn("The controller do not set up exception handler, should set up it properly");
				throw e;
			}

			if (exHandler.canHandle(e)) {
				_errorObject = exHandler.handleException(e, null);
			} else {
				throw e;
			}

			if (logger.isDebugEnabled()) {
				logger.debug("Application exception or binding exception is found in LicMultiActionController.");
				logger.debug("errorView=" + errorView);
			}

			if (errorView == null) {
				errorView = getDefaultErrorView();
			}

			// Resolve the method name
			String _methodName = getMethodNameResolver().getHandlerMethodName(request);
			String _handleMethodErrorName = "on" + StringUtils.capitalize(_methodName) + "Error";
			ModelAndView _errorModelAndView = null;

			if (logger.isDebugEnabled()) {
				logger.debug("The method to handle method error is "+ _handleMethodErrorName);
			}

			try {
				_errorModelAndView = invokeNamedMethod(_handleMethodErrorName,
						request, response);
				if (logger.isDebugEnabled()) {
					logger.debug("The error Model And view is constructed.");
					logger.debug("The view is " + _errorModelAndView.getView());
				}

			} catch (NoSuchRequestHandlingMethodException methodNotFound) {
				if (logger.isDebugEnabled()) {
					logger.debug("The method to handle method error is NOT found !!!!!");
				}
			}

		} finally {
			log.setResponeTime(new Date(System.currentTimeMillis()));
			try {
				operLogSV.insertLog(log);
			} catch (Exception e) {
				e.printStackTrace();
			}

		}

		return _mv;
	}

	/**
	 * Override to add custom editor. <br>
	 * Currently the newly added custom editor:
	 */
	protected void initBinder(HttpServletRequest request,
			ServletRequestDataBinder binder) throws Exception {

		super.initBinder(request, binder);
		// add custom property editor to trim the String.
		binder.registerCustomEditor(String.class, new StringTrimmerEditor(false));
	}

	protected String getCommandName(Object command) {

		if (!StringUtils.hasText(commandName)) {
			return super.getCommandName(command);
		}

		return getCommandName();
	}

	/**
	 * Get the default error view name.
	 * 
	 * @return the default error view name.
	 */
	private String getDefaultErrorView() {

		return WebConstants.DEFAULT_APP_ERROR_VIEW_NAME;
	}

	public ExceptionHandler getExHandler() {
		return exHandler;
	}

	public void setExHandler(ExceptionHandler exHandler) {
		this.exHandler = exHandler;
	}

	public String getErrorView() {
		return errorView;
	}

	public void setErrorView(String errorView) {
		this.errorView = errorView;
	}

	public String getFormView() {
		return formView;
	}

	public void setFormView(String formView) {
		this.formView = formView;
	}

	public void setCommandName(String commandName) {
		this.commandName = commandName;
	}

	public String getCommandName() {
		return commandName;
	}

	public void afterPropertiesSet() throws Exception {

		if (exHandler == null) {
			logger.warn("The controller does not set up any exception handler, please set it or add parent in your controller configuration file");
		}
	}
}
